            
<template>
    <div class="main">
        <!-- 顶部导航（组件复用） -->
        <!-- <my-top-nav></my-top-nav> -->

        <!-- 中部内容 -->
        <div class="center_context" style="height: calc(100vh - 70px)">

            <!--地图：精彩内容开始-->
            <div class="map-display" id="mapDiv">
            </div>
            <!--“整饰”-->
            <div class="tool-item-panel mapDecorateTools" id="mapDecorateTools" :class="{ 'layer-hide': decoratePanelVisible }"
                data-toolPanel-title="Decorate">
                <div class="map-tool-item" id="CoordinateDisplay" title="坐标" @click="coordinateShow = !coordinateShow">
                    <img src="../assets/images/map_icons/Coordinate.png">
                    <span>坐标</span>
                </div>
                <div class="map-tool-item" id="ScaleDisplay" title="比例尺" @click="scaleShow = !scaleShow">
                    <img src="../assets/images/map_icons/Scale.png">
                    <span>比例尺</span>
                </div>
            </div>
            <!--坐标与比例尺-->
            <div class="coordinateAndScaleBar">
                <!--地图比例尺-->
                <div id="scaleBarDiv" class="map-scalebar" v-show="scaleShow">
                    <div id="scaleBar"></div>
                </div>
                <!--地图坐标 (id必须为mouse-position，否则无法正常显示)-->
                <div class="map-decorate map-coordinate custom-mouse-position" id="mouse-position" v-show="coordinateShow">
                </div>
            </div>

            <!-- 地图左上角按钮栏 -->
            <div id="myToolBtns" class="mytool-btns">
                <!-- 按钮组 -->
                <div id="buttonDiv" style="float: left;">
                    <!-- 地图整饰控制按钮 -->
                    <div class="navbtn-items" v-if=decorateShow @click="togglePanel('decoratePanelVisible', 'decorateFlag')"
                        title="地图整饰控制" id="decorateBtn">
                        <img src="../assets/images/map_icons/Decorate.png">
                        <img v-show="decorateFlag" src="../assets/images/map_icons/selectPoint.png" class="item-selected">
                    </div>
                    <!-- 按钮1：图层管理 -->
                    <div class="navbtn-items" v-if=layerShow @click="togglePanel('lyrPanelVisible', 'layerFlag')" title="图层"
                        id="layerBtn">
                        <img src="../assets/images/map_icons/layer.png">
                        <img v-show="layerFlag" src="..\assets\daiban.png" class="item-selected">
                    </div>
                    <!-- 属性查询图标按钮 -->
                    <div class="navbtn-items" v-if=attrQueryPanelShow
                        @click="togglePanel('attrQueryPanelVisible', 'attrQueryFlag')" title="属性查询" id="attrQueryBtn">
                        <img src="../assets/images/map_icons/shuxing.png">
                        <img v-show="attrQueryFlag" src="../assets/images/map_icons/selectPoint.png" class="item-selected">
                    </div>
                </div> <!-- buttonDiv结束 -->
                <!--图层控制面板-->
                <div id="layerControl" class="layerControl" :class="{ 'layer-hide': lyrPanelVisible }">
                    <div class="title"><label>图层列表</label></div>
                    <ul id="layerTree" class="layerTree"></ul>
                </div>
            </div> <!-- myToolBtns结束 -->



        </div> <!-- 中部内容结束 -->
    </div> <!-- 最外层Div结束 -->
</template>

<script>

import 'ol/ol.css';
import { defaults, Attribution, Zoom, ZoomSlider, ZoomToExtent, OverviewMap, ScaleLine, MousePosition } from 'ol/control';
import { createStringXY } from 'ol/coordinate';
import { XYZ, Vector } from 'ol/source';
import { Tile, Vector as lVector, Heatmap as lHeatMap  } from 'ol/layer';
import { Map, View, Overlay, Feature} from 'ol';
import { Style, Fill, Stroke, Circle, Text, Circle as CircleStyle, Icon, RegularShape } from 'ol/style';
import { Point, LineString, Polygon } from 'ol/geom';
import { Draw } from 'ol/interaction'; //后续还要用到,Select
import { getArea, getLength } from 'ol/sphere';
import { unByKey } from 'ol/Observable';

export default {
    name: 'soilusemap',
    components: {
        // MyTopNav: TopNav
    },
    props: {
        /*mapCtrlTools:{
            type:Array,
            default:function () {
                return []
            }
        },
        lyrdata: {
            type: Array,
            default: []
        },
        mapParams: {
            type: Object,
            default: {}
        },*/
    },
    data() {
        return {
            myMapProjection: 'EPSG:4326',//设置为WGS84坐标系，将在地图初始化、量测等功能中调用
            myZoomExtent: [70, 22, 110, 55],
            /**功能组按钮控制**/
            layerShow: true, //图层按钮的控制-功能启动图标按钮，默认false不显示
            decorateShow: true,//鹰眼-功能启动图标按钮，默认false不显示

            /**地图各悬浮面板的可视状态**/
            layerPanelVisible: true, //默认true为隐藏
            scaleShow: true, //显示比例尺,默认false不显示
            decoratePanelVisible: true, //默认true为隐藏

            /*选中显示红色小标志*/
            layerFlag: true, //图层选中显示红色小标志，默认false为隐藏
            decorateFlag: false, //鹰眼选中显示红色小标志，默认false为隐藏

        }
    },
    methods: {
        //切换面板功能函数
        togglePanel(attr, attr2) {
            this[attr] = !this[attr];
            this[attr2] = !this[attr2];
        },

        //地图初始化方法
        InitMap() {
            //地图初始化方法
            let that = this;

            //初始化地图容器
            let map = new Map({
                target: 'mapDiv',
                view: new View({
                    center: [109.43, 33.48],
                    zoom: 7,
                    projection: 'EPSG:4326',
                }),
            }); this.map = map;

            let myVecLayer1 = new Zondy.Map.GdbpLayer("", ["gdbp://MapGISLocalPlus/2023开发大赛/sfcls/玄奘西行途径城市"], {  
                ip: "jlu3s.com",
                port: "35017",                
                title: "玄奘西行途径城市-矢量图层", 
                visible: true, 
            });
            //别忘了把地图文档图层加载到地图中
            map.addLayer(myVecLayer1)

            let myVecLayer2 = new Zondy.Map.GdbpLayer("", ["gdbp://MapGISLocalPlus/2023开发大赛/sfcls/土壤类型图"], {
                ip: "jlu3s.com",
                port: "35017",
                title: "土壤类型图",
                visible: true,
            });
            //将地图文档图层加载到地图中
            map.addLayer(mapVecLayer2);

            let myVecLayer3 = new Zondy.Map.GdbpLayer("", ["gdbp://MapGISLocalPlus/2023开发大赛/sfcls/粮食产量图"], {
                ip: "jlu3s.com",
                port: "35017",
                title: "粮食产量图",
                visible: true,
            });
            //将地图文档图层加载到地图中
            map.addLayer(mapVecLayer3);

            let myVecLayer4 = new Zondy.Map.GdbpLayer("", ["gdbp://MapGISLocalPlus/2023开发大赛/sfcls/交通运输情况"], {
                ip: "jlu3s.com",
                port: "35017",
                title: "交通运输图",
                visible: true,
            });
            //将地图文档图层加载到地图中
            map.addLayer(mapVecLayer4);

            //初始化地图文档图层对象
            let myVecLayer5 = new Zondy.Map.GdbpLayer("", ["gdbp://MapGISLocalPlus/2023开发大赛/sfcls/土地利用现状"], {
                ip: "jlu3s.com",
                port: "35017",
                title: "土地利用现状图",
                visible: true,
            });
            //将地图文档图层加载到地图中
            map.addLayer(mapVecLayer5);

            //region 地图测量功能
            //定义“测量”和“勾绘”过程中用到的临时工作矢量层
            that.drawSource = new Vector() //图层数据源
            that.drawVector = new lVector({
                title: '临时工作图层（绘制图形用）', //在图层面板中显示
                source: that.drawSource,
                style: new Style({
                    //图层样式
                    fill: new Fill({
                        color: 'rgba(255, 255, 255, 0.2)' //填充颜色
                    }),
                    stroke: new Stroke({
                        color: '#ffcc33', //边框颜色
                        width: 2 // 边框宽度
                    }),
                    image: new Circle({
                        radius: 7,
                        fill: new Fill({
                            color: '#ffcc33'
                        })
                    })
                })
            })
            //OpenLayer5中已封装好与椭球相关的getLength和getArea方法
            //let wgs84Sphere = new ol.Sphere(6378137); //定义一个球对象
            let sketch//当前绘制的要素
            let helpTooltipElement//帮助提示框对象
            let helpTooltip//帮助提示框显示的信息
            let measureTooltipElement//测量工具提示框对象
            let measureTooltip//测量工具中显示的测量值
            let continuePolygonMsg = '继续点击绘制多边形'//当用户正在绘制多边形时的提示信息文本
            let continueLineMsg = '继续点击绘制线'//当用户正在绘制线时的提示信息文本
            let pointerMoveHandler = function (evt) {//鼠标移动事件处理函数
                if (evt.dragging) {
                    return
                }
                /** @type {string} */
                let helpMsg = '点击开始绘制' //当前默认提示信息
                //判断绘制几何类型设置相应的帮助提示信息
                if (sketch) {
                    let geom = sketch.getGeometry()
                    if (geom instanceof Polygon) helpMsg = continuePolygonMsg //绘制多边形时提示相应内容
                    else if (geom instanceof LineString) helpMsg = continueLineMsg //绘制线时提示相应内容
                }
                helpTooltipElement.innerHTML = helpMsg //将提示信息设置到对话框中显示
                helpTooltip.setPosition(evt.coordinate) //设置帮助提示框的位置
            }
            //鼠标移动与动态帮助提示
            function mapPointMove() {
                map.on('pointermove', pointerMoveHandler) //地图容器绑定鼠标移动事件，动态显示帮助提示框内容
            }

            let typeSelect = 'area' //全局变量，默认值为‘area’测面
            let distanceDiv = document.getElementById('myMeasureDistance') //测量类型对象-距离
            let areaDiv = document.getElementById('myMeasureArea') //测量类型对象-面积
            let draw //全局变量，以便后续移除

            //点击测距离    
            document.getElementById("myMeasureDistance").addEventListener("click", function () {
                console.log("（距离）量测");
                that.map.removeLayer(that.drawVector) //先移除再添加，否则控制台报错
                that.map.addLayer(that.drawVector)
                that.map.removeInteraction(draw) //移除绘制图形
                typeSelect = 'distance'
                addInteraction() //添加绘图进行测量
                mapPointMove() //鼠标移动与动态帮助提示
            }.bind(this)
            ) //监听量测中“距离”按钮的点击事件

            //点击测面积    
            document.getElementById("myMeasureArea").addEventListener("click", function () {
                console.log("（面积）量测");
                that.map.removeLayer(that.drawVector)
                that.map.addLayer(that.drawVector)
                that.map.removeInteraction(draw) //移除绘制图形
                typeSelect = 'area'
                addInteraction() //添加绘图进行测量
                mapPointMove() //鼠标移动与动态帮助提示
            }.bind(this)
            ) //监听量测中“面积”按钮的点击事件

            //点击“清除”量测结果    
            document.getElementById("myClearMeasure").addEventListener("click", function () {
                console.log("（清除）量测");
                if (draw) {
                    draw.setActive(false) //取消激活状态，以便退出绘制
                }
                let ols = that.map.getOverlays()
                ols.clear() //把所有覆盖物（测量结果）都清楚掉
                that.map.removeLayer(that.drawVector) //把vector图层也清除掉，从而清除测量图形
                //注：此处不能通过var定义局部变量，会导致全局vector调用局部source而报错
                that.drawSource = null //先清空全局变量source
                that.drawSource = new Vector() //再实例化一个矢量图层给全局变量source，从而消除上次测量残留
                that.drawVector.setSource(that.drawSource) //更新vector的新源，避免本次量测残留图形对后续新量测的影响

            }.bind(this)
            ) //监听量测中“清除”按钮的点击事件

            /**
             * 加载交互绘制控件函数
             */
            function addInteraction() {
                let type = typeSelect == 'area' ? 'Polygon' : 'LineString'
                draw = new Draw({
                    source: that.drawSource, //测量绘制层数据源
                    type: /** @type {ol.geom.GeometryType} */ (type), //几何图形类型
                    style: new Style({
                        //绘制几何图形的样式
                        fill: new Fill({
                            color: 'rgba(255, 255, 0, 0.2)' //浅黄色
                        }),
                        stroke: new Stroke({
                            color: 'rgba(255, 255, 0, 0.7)', //黄色
                            lineDash: [10, 10],
                            width: 2
                        }),
                        image: new Circle({
                            radius: 5,
                            stroke: new Stroke({
                                color: 'rgba(0, 0, 0, 0.7)' //黑色
                            }),
                            fill: new Fill({
                                color: 'rgba(255, 0, 255, 0.5)' //紫红色
                            })
                        })
                    })
                })
                that.map.addInteraction(draw)

                createMeasureTooltip() //创建测量工具提示框
                createHelpTooltip() //创建帮助提示框

                let listener
                //绑定交互绘制工具开始绘制的事件
                draw.on('drawstart', function (evt) {
                    // set sketch
                    sketch = evt.feature //绘制的要素

                    /** @type {ol.Coordinate|undefined} */
                    let tooltipCoord = evt.coordinate // 绘制的坐标
                    //绑定change事件，根据绘制几何类型得到测量长度值或面积值，并将其设置到测量工具提示框中显示
                    listener = sketch.getGeometry().on('change', function (evt) {
                        let geom = evt.target //绘制几何要素
                        let output
                        if (geom instanceof Polygon) {
                            output = formatArea(/** @type {ol.geom.Polygon} */(geom)) //面积值
                            tooltipCoord = geom.getInteriorPoint().getCoordinates() //坐标
                        } else if (geom instanceof LineString) {
                            output = formatLength(/** @type {ol.geom.LineString} */(geom)) //长度值
                            tooltipCoord = geom.getLastCoordinate() //坐标
                        }
                        measureTooltipElement.innerHTML = output //将测量值设置到测量工具提示框中显示
                        measureTooltip.setPosition(tooltipCoord) //设置测量工具提示框的显示位置
                    })
                },
                    this
                )
                //绑定交互绘制工具结束绘制的事件
                draw.on('drawend', function (evt) {
                    measureTooltipElement.className = 'tooltip tooltip-static' //设置测量提示框的样式
                    measureTooltip.setOffset([0, -7])
                    // unset sketch
                    sketch = null //置空当前绘制的要素对象

                    // unset tooltip so that a new one can be created
                    measureTooltipElement = null //置空测量工具提示框对象
                    createMeasureTooltip() //重新创建一个测试工具提示框显示结果

                    helpTooltipElement.style.display = 'none'
                    unByKey(listener)
                    draw.setActive(false) //取消激活状态，以便退出绘制
                },
                    this
                )
            }

            /**
             *创建一个新的帮助提示框（tooltip）
            */
            function createHelpTooltip() {
                if (helpTooltipElement) {
                    helpTooltipElement.parentNode.removeChild(helpTooltipElement)
                }
                helpTooltipElement = document.createElement('div')
                helpTooltipElement.className = 'tooltip hidden'
                helpTooltip = new Overlay({
                    element: helpTooltipElement,
                    offset: [15, 0],
                    positioning: 'center-left'
                })
                that.map.addOverlay(helpTooltip)
            }
            /**
             *创建一个新的测量工具提示框（tooltip）
            */
            function createMeasureTooltip() {
                if (measureTooltipElement) {
                    measureTooltipElement.parentNode.removeChild(measureTooltipElement)
                }
                measureTooltipElement = document.createElement('div')
                measureTooltipElement.className = 'tooltip tooltip-measure'
                measureTooltip = new Overlay({
                    element: measureTooltipElement,
                    offset: [0, -15],
                    positioning: 'bottom-center'
                })
                that.map.addOverlay(measureTooltip)
            }

            /**
             * 测量长度输出
             * @param {ol.geom.LineString} line
             * @return {string}
             */

            let formatLength = function (line) {
                let length = getLength(line, {
                    projection: that.myMapProjection
                })
                let output
                if (length > 100) {
                    output = Math.round((length / 1000) * 100) / 100 + ' ' + 'km'
                } else {
                    output = Math.round(length * 100) / 100 + ' ' + 'm'
                }
                return output
            }

            /**
            * 测量面积输出
            * @param {ol.geom.Polygon} polygon
            * @return {string}
            */
            let formatArea = function (polygon) {
                //第二个formatArea函数了，这里还是用area全局变量吧
                let area = getArea(polygon, {
                    projection: that.myMapProjection
                })
                let output
                if (area > 10000) {
                    output = Math.round((area / 1000000) * 100) / 100 + ' ' + 'km<sup>2</sup>'
                } else {
                    output = Math.round(area * 100) / 100 + ' ' + 'm<sup>2</sup>'
                }
                return output
            }

            //endregion 测量功能    

            /**地图控件（代码块开始）**/

            //缩放控件
            function addZoomControl() {
                if (map != null) {
                    var zoom = new Zoom()
                    map.addControl(zoom)
                }
            }
            //复位
            function addZoomExtentControl() {
                if (map != null) {
                    var zoomToExtent = new ZoomToExtent({
                        extent: that.myZoomExtent,
                    })
                    map.addControl(zoomToExtent)
                }
            }
            //添加坐标
            function addMousePositionControl() {
                if (map != null) {
                    var mousePositionControl = new MousePosition({
                        //坐标格式
                        coordinateFormat: createStringXY(5),//坐标小数位数
                        //地图投影坐标系（若未设置则输出为默认投影坐标系下的坐标）
                        projection: 'EPSG:4326',
                        //坐标信息显示样式类名，默认是'ol-mouse-position'
                        className: 'custom-mouse-position',
                        //显示鼠标位置信息的目标容器
                        target: document.getElementById('mouse-position'),
                        //未定义坐标的标记
                        undefinedHTML: '&nbsp;',
                    })
                    map.addControl(mousePositionControl)
                }
            }
            //比例尺控件
            function addScaleControl() {
                if (map != null) {
                    //实例化比例尺控件（ScaleLine）
                    var scaleLineControl = new ScaleLine({
                        //设置比例尺单位，degrees、imperial、us、nautical、metric（度量单位）
                        units: 'metric',
                        target: 'scaleBar',
                        className: 'ol-scale-line'
                    })
                    map.addControl(scaleLineControl)
                }
            }
            /*集中调用*/
            addZoomControl();
            addZoomExtentControl();
            addMousePositionControl();
            addScaleControl();

            /**地图控件（代码块结束）**/

            /**图层管理面板（代码块开始）**/

            /**
             * 加载图层列表数据
             * @param {ol.Map} map 地图对象
             * @param {string} id 图层列表容器ID
             */
            function loadLayersControl(map, id) {
                //图层目录容器
                var treeContent = document.getElementById(id);
                //获取地图中所有图层
                var layers = map.getLayers();

                for (var i = 0; i < layers.getLength(); i++) {
                    let t = layers.array_[i].get('title');
                    let tv = layers.array_[i].getVisible();

                    //新增li元素，用来承载图层项
                    var elementLi = document.createElement('li');
                    // 添加子节点
                    treeContent.appendChild(elementLi);
                    //创建复选框元素
                    var elementInput = document.createElement('input');
                    elementInput.type = "checkbox";
                    elementInput.name = "layers";
                    elementLi.appendChild(elementInput);
                    //创建label元素
                    var elementLable = document.createElement('label');
                    elementLable.className = "layer";
                    //设置图层名称
                    setInnerText(elementLable, t);
                    elementLi.appendChild(elementLable);
                    //设置图层默认显示状态
                    if (tv) {
                        elementInput.checked = true;
                    }
                    //为checkbox添加变更事件
                    addChangeEvent(elementInput, layers.array_[i]);
                }
            }
            /**
             * 为checkbox元素绑定变更事件
             * @param {input} element checkbox元素
             * @param {ol.layer.Layer} layer 图层对象
             */
            function addChangeEvent(element, layer) {
                element.onclick = function () {
                    if (element.checked) {
                        //显示图层
                        layer.setVisible(true);
                    }
                    else {
                        //不显示图层
                        layer.setVisible(false);
                    }
                };
            }
            /**
             * 动态设置元素文本内容（兼容）
             */
            function setInnerText(element, text) {
                if (typeof element.textContent == "string") {
                    element.textContent = text;
                } else {
                    element.innerText = text;
                }
            }

            //别忘了调用函数(传入参数）
            loadLayersControl(map, "layerTree");

            /**图层管理面板（代码块结束）**/



        },//end of InitMap()
        F2() {

        },
        F3() {

        },
        F4() {

        },
        F5() {

        },

    },
    created() {

    },
    mounted() {
        // 页面各元素挂载就绪后执行
        this.InitMap();
    },
    watch: {

    },
    computed: {

    }
}
</script>

<style scoped>
@import '../assets/css/zdmap.css';

.layer-hide {
    display: none;
}


/*工具项：整饰-->>对应下拉面板*/
.mapDecorateTools {
    position: relative;
    width: 85px;
    left: 10em;
    background-color: #ffffff;
    box-shadow: 4px 4px 10px #888888;
    z-index: 4;
    /*高于lyrBox的3*/
}

/*地图整饰（坐标、比例尺、图例均通用）*/
.map-decorate {
    position: absolute;
    z-index: 2;
}

/*比例尺位置*/
/*用于覆盖原生比例尺的样式*/
.ol-scale-line {
    background: #f39c12;
    border-radius: 4px;
    bottom: 8px;
    left: -20em;
    /*约等于16px*20=320px*/
    padding: 2px;
    position: absolute;
    height: 26px;
}

.map-scalebar {
    position: absolute;
    bottom: 6px;
    left: 10em;
}

/*坐标位置*/
.map-coordinate {
    left: 315px;
    /*right:105px;*/
    bottom: 15px;
    /*top:10px;*/
    margin: 2px 6px;
    padding: 2px 4px;
    font-family: Arial;
    color: #ffffff;
    background-color: #f39c12;
    /*min-width: 150px;*/
    border-radius: 4px;
    height: 20px;
}

/* 地图容器基本样式 */
.map-display {
    position: absolute;
    width: 100%;
    height: 100%;
    background-color: darkgray;
}

/*地图工具栏相关样式  */
.mytool-btns {
    position: relative;
    /*left: 10px;*/
    margin-left: 2.5em;
    top: 10px;
    height: 60px;
    /*width:320px;*/
    /*以免ol-popup被地图工具按钮div给挡住而无法点击关闭面板按钮*/
    width: 450px;
    /*以免ol-popup被地图工具按钮div给挡住而无法点击关闭面板按钮*/
}

.navbtn-items {
    float: left;
    margin: 0 5px;
    /*border-right: 1px solid #788897; !*显示右侧的边框线*!*/
    position: relative;
    width: 40px;
    height: 40px;
    border-radius: 50%;
    background-color: white;
    text-align: center;
}

.navBtnDiv {
    /*width: auto;*/
    /*background-color:rgba(0,0,0,0);*/
    margin-left: 55px;
    /*margin-top: 5px;*/
}

.navbtn-btn {
    margin-right: 10px;
}

.navbtn-items:hover {
    cursor: pointer;
}

.navbtn-items>img {
    width: 36px;
    height: 36px;
    padding: 5px;
}

.item-selected {
    position: absolute;
    width: 25px !important;
    height: 25px !important;
    left: 15px !important;
    bottom: 0;
}</style>